package com.xyz.app.config;


import com.xyz.app.shiro.JwtRealm;
import com.xyz.app.shiro.JwtShiroFilter;
import com.xyz.app.shiro.UserRealm;
import com.xyz.app.shiro.UserShiroFilter;
import com.xyz.service.CustomerService;
import com.xyz.shiro.CustomizedOnlySingleModularRealmAuthenticator;
import com.xyz.shiro.WithIngoresShiroFilterFactoryBean;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.*;

//https://jinnianshilongnian.iteye.com/blog/2041909

@Configuration
public class ShiroConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean(){

        FilterRegistrationBean registration = new FilterRegistrationBean(new DelegatingFilterProxy("shiroFilter"));
        registration.addUrlPatterns("/*"); //
        registration.setName("shiroFilter");
        registration.setOrder(1);
        return registration;
    }

//    @Bean
//    public Authenticator authenticator(CustomerService customerService) {
//        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
//        authenticator.setRealms(Arrays.asList(jwtShiroRealm(customerService), userRealm(customerService)));
//        authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
//        return authenticator;
//    }

    @Bean
    protected SessionStorageEvaluator sessionStorageEvaluator(){
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }


    @Bean("dbRealm")
    public Realm userRealm(CustomerService customerService, EhCacheCacheManager ehCacheCacheManager) {
        UserRealm userRealm = new UserRealm(customerService, ehCacheCacheManager);
        return userRealm;
    }

    @Bean("jwtRealm")
    public Realm jwtShiroRealm(CustomerService customerService, EhCacheCacheManager ehCacheCacheManager) {
        JwtRealm myShiroRealm = new JwtRealm(customerService, ehCacheCacheManager);
        return myShiroRealm;
    }

    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager =  new DefaultWebSessionManager();
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(CustomerService customerService, EhCacheCacheManager ehCacheCacheManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setAuthenticator(modularRealmAuthenticator());
        securityManager.setRealms(Arrays.asList(
                jwtShiroRealm(customerService, ehCacheCacheManager),
                userRealm(customerService, ehCacheCacheManager)));
        return securityManager;
    }

    /**
     * 设置过滤器
     */
    @Bean(name = "shiroFilter")
    public WithIngoresShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager, CustomerService userService, EhCacheCacheManager ehCacheCacheManager){
        WithIngoresShiroFilterFactoryBean factoryBean = new WithIngoresShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filterMap = factoryBean.getFilters();
        filterMap.put("authcFilter", createuUserFilter(userService, ehCacheCacheManager));
        filterMap.put("jwtFilter", jwtFilter(userService, ehCacheCacheManager));
        factoryBean.setFilters(filterMap);
        factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition());
        return factoryBean;
    }

    public Authenticator modularRealmAuthenticator(){
        return new CustomizedOnlySingleModularRealmAuthenticator();
    }

    public UserShiroFilter createuUserFilter(CustomerService userService, EhCacheCacheManager ehCacheCacheManager){
        UserShiroFilter userShiroFilter = new UserShiroFilter(userService,ehCacheCacheManager);
        List<String> loginUrls = new ArrayList<String>();
        loginUrls.add("/login.json");
        userShiroFilter.setLoginUrls(loginUrls);
        List<String> ajaxSuffixes = new ArrayList<>();
        ajaxSuffixes.add(".json");
        userShiroFilter.setAjaxSuffix(ajaxSuffixes);
        return userShiroFilter;
    }

    public JwtShiroFilter jwtFilter(CustomerService userService, EhCacheCacheManager ehCacheCacheManager){
        JwtShiroFilter filter = new JwtShiroFilter(userService,ehCacheCacheManager);
        return filter;
    }


    protected Map<String,String> shiroFilterChainDefinition() {
        Map<String,String> chainDefinition = new HashMap<>();
        chainDefinition.put("/login.json", "noSessionCreation,authcFilter");
        chainDefinition.put("/ylzx/*","noSessionCreation,jwtFilter");
        chainDefinition.put("/loginstatus.json","noSessionCreation,jwtFilter");
        chainDefinition.put("/logout", "noSessionCreation");
        chainDefinition.put("/image/**", "anon");
        return chainDefinition;
    }
}
